package com.mjf.scala.chapter05

/**
 * 高阶函数之函数作为返回值返回
 */
object Scala06_TestFunReturn {
  def main(args: Array[String]): Unit = {

    def f1(): (Int) => Int = {
      var a = 10
      def f2(b: Int): Int = {
        a + b
      }
      f2 _    // 将函数f2作为返回值返回
    }

//    println(f1()(20))

    // 执行f1函数返回f2,将返回的f2赋值给ff变量
    val ff: Int => Int = f1()

    // 闭包：内存函数f2要访问外层函数f1局部变量a,当外层函数f1执行结束以后，f1会释放栈内存，
    //      但是会自动的延长f1函数的局部变量的生命周期，和内存函数f2形成一个闭合的效果，这种效果称为闭包

    // 闭包 = 外层函数的局部变量 + 内层函数

    // 如果存在闭包，那么编译器会生成包含 $anonfun$ 的字节码文件

    // 调用ff函数，其实就是调用f2
    println(ff(20))


    // -------------------------------------------------
    // 以上代码可以做一下简化
/*    def f1(): (Int) => Int = {
      var a = 10
      def f2(b: Int): Int = {
        a + b
      }
      f2 _    // 将函数f2作为返回值返回
    }*/

    def f3() = {
      var a = 10
      (b: Int)  => a + b
//      a + _     // 不建议这样简化，这样推导不出来类型
    }

    println(f3()(20))


    // ----------------------------------------
    // 柯里化
    // 将一个函数的一个参数列表中的多个参数，拆分成多个参数列表
    // 简化闭包代码的编写
    def f4()(b: Int) = {
      var a = 10
      a + b
    }

    // f4在执行的时候会转化为下面的结构
/*    def f3() = {
      var a = 10
      (b: Int)  => a + b
    }*/

    f4()(20)

    // 柯里化，是对函数嵌套的简化，但是这里只有一层函数体，如果每层完成的业务逻辑不一样，一个函数体如何处理

  }
}
